﻿namespace Algo.Demo
{
    using System;
    using System.Diagnostics;
    using System.Diagnostics.Contracts;

    using JetBrains.Annotations;

    internal sealed class TestResult : IAlgoExtensions, IMetricsExtension
    {
        private readonly object _lockObject = new object();
        private readonly Type _algoType;
        private readonly Stopwatch _stopwatch = new Stopwatch();
        private int _iterationsCount;

        public TestResult([NotNull] Type algoType)
        {
            Contract.Requires<ArgumentNullException>(algoType != null);
            _algoType = algoType;
        }

        public string AlgoName
        {
            [NotNull] get
            {
                Contract.Ensures(Contract.Result<string>() != null);
                return _algoType.Name;
            }
        }

        public long ElapsedTicks { get; private set; }

        public int IterationsCount
        {
            get
            {
                return _iterationsCount;
            }
        }

        public bool TryGet<TBehaviour>(out TBehaviour behaviour)
        {
            if (typeof(TBehaviour) == typeof(IMetricsExtension))
            {
                behaviour = (TBehaviour)(object)this;
                return true;
            }

            behaviour = default(TBehaviour);
            return false;
        }

        public void RegisterIterations(int count)
        {
            lock (_lockObject)
            {
                _iterationsCount += count;
            }
        }

        public void Start()
        {
            _stopwatch.Start();
        }

        public void Stop()
        {
            _stopwatch.Stop();
            ElapsedTicks = _stopwatch.ElapsedTicks;
        }

        public override string ToString()
        {
            return String.Format("{0}\tduration(ms): {1}\titerations: {2}", AlgoName, TimeSpan.FromTicks(ElapsedTicks).TotalMilliseconds, IterationsCount);
        }
    }
}